<?php
namespace Wosh;

define('RESOURCE_ROOT',ROOT.DS.'public');
define('SWOOLE_ENTRY',true);

class WebServer{

    static $http;
    static $instance;
    static $config;
    static $configALl;
    static $HTTP_REQUEST;
    static $HTTP_RESPONSE;
    static $tid;
    
    protected function __construct()
    {
        self::$configALl = include('config.php');
        return $this;
    }

    public function runAll($count=1){
        for($i=0;$i<$count;$i++){
            if($i>count(self::$configALl )) break;
            $process = new \swoole_process(function(\swoole_process $worker)use($i){
                self::instance()->run($i);
            }, true);
            $process->start();
        }
        echo 'there is '.$i.' of Server started';
    }

    /**
     *
     */
    public function run($tid=0){
        self::$tid = $tid;
        self::$config = self::$configALl[self::$tid];
        /*
         * create http server
         */
        self::$http = new \swoole_http_server(self::$config['DOMAIN'], self::$config['PORT'], SWOOLE_SOCK_ASYNC);

        /*
         * http server started listener
         * */
        self::$http->on("start", function ($server) {
            echo "Swoole http server is started at http://".self::$config['DOMAIN'].":".self::$config['PORT']."\n";
        });

        /*
         * http server request listener
         * */
        self::$http->on('request', function($HTTP_REQUEST,$HTTP_RESPONSE){
            self::$HTTP_REQUEST = $HTTP_REQUEST;
            self::$HTTP_RESPONSE = $HTTP_RESPONSE;

            $uri = $HTTP_REQUEST->server['request_uri'];

            $_GET = !is_null($HTTP_REQUEST->get)?$HTTP_REQUEST->get:[];
            $_POST = !is_null($HTTP_REQUEST->post)?$HTTP_REQUEST->post:[];
            @$_REQUEST = array_merge($_GET,$_POST);
            $_COOKIE = !is_null($HTTP_REQUEST->cookie)?$HTTP_REQUEST->cookie:[];
            $_FILES = !is_null($HTTP_REQUEST->files)?$HTTP_REQUEST->files:[];
            $_SERVER = !is_null($HTTP_REQUEST->server)?$HTTP_REQUEST->server:[];
            $_SERVER = array_change_key_case( $_SERVER,CASE_UPPER);

            /* rewrite url */
            $norewrite = true;
            if(!empty(self::$config['routers'])){
                foreach(self::$config['routers'] as $router){
                    $norewrite = false;
                    $bl = false;
                    if(!empty($router['cond'])){
                        $norewrite = false;
                        foreach($router['cond'] as $cond){
                            if(strpos('!',$cond)>=0){
                                $cond = substr($cond,1);
                                $bl = true;
                            }
                            if($cond(ROOT.$uri)&$bl){
                                $norewrite = true;
                                break;
                            }
                        }
                    }
                    if(!$norewrite){
                        $uri = preg_replace($router['rules'],$router['rewrite'],$uri,-1,$count);
                        break;
                    }
                }
            }
            if(strpos('.',$uri)<=0 && $norewrite) $uri = $uri.self::$config['DEFAULT_INDEX'];

            /* explode the url for php_self and path_info */
            $arr = explode('.',$uri);
            /* uri is not a file and no routers, TODO others examples file list page or 404 output */
            if(count($arr)==1){
                self::$HTTP_RESPONSE->status(404);
                self::$HTTP_RESPONSE->end('request path not found : '.$uri);
                return;
            }
            $ext = explode(DS,$arr[1]);
            $php_self = $arr[0].'.'.$ext[0];
            $realfile = ROOT.$php_self;
            $pathinfo = $ext;
            unset($pathinfo[0]);
            if(!$norewrite) $_SERVER['SCRIPT_FILENAME'] = ROOT.$php_self;

            /* get GLOBALS $_SESSION */
            if(empty($_COOKIE[self::$config['SESSION_NAME']])){
                $session_name = md5(rand(100000,999999)).time().chr(rand(65,90)).chr(rand(97,122));
                $_COOKIE[self::$config['SESSION_NAME']] = $session_name;
                self::$HTTP_RESPONSE->cookie(self::$config['SESSION_NAME'],$session_name);
            }
            if(!file_exists(self::$config['SESSION_SAVE_PATH']) || !is_dir(self::$config['SESSION_SAVE_PATH']))mkdir(self::$config['SESSION_SAVE_PATH'],0777,true);
            $_SESSION = unserialize(file_exists(self::$config['SESSION_SAVE_PATH'].DS.$_COOKIE[self::$config['SESSION_NAME']]) ? file_get_contents(self::$config['SESSION_SAVE_PATH'].DS.$_COOKIE[self::$config['SESSION_NAME']]) : serialize([]));

            /* get the request php file, and output */
            $rend = false;
            if(in_array($ext[0],self::$config['PHP_EXT'])){ /* php script file request */
                if(file_exists($realfile)) {
                    $_SERVER['PHP_SELF'] = $php_self;
                    $_SERVER['PATH_INFO'] = DS.implode(DS,$pathinfo);
                    $result = include($realfile);
                    self::$HTTP_RESPONSE->end($result);
                }else{
                    self::$HTTP_RESPONSE->status(404);
                    self::$HTTP_RESPONSE->end('file not found : '.$realfile);
                }
                $rend = true;
            }
            if(!$rend){
                /* other resource files request, the file extension name had set in config */
                self::$HTTP_RESPONSE->header('content-type',array_key_exists($ext[0],self::$config['EXT_TYPE'])?self::$config['EXT_TYPE'][$ext[0]]:self::$config['EXT_TYPE']['*']);
                if(file_exists(RESOURCE_ROOT.$php_self)) {
                    self::$HTTP_RESPONSE->end(file_get_contents(RESOURCE_ROOT.$php_self));
                    $rend = true;
                }
            }
            if(!$rend){
                self::$HTTP_RESPONSE->status(404);
                self::$HTTP_RESPONSE->end('resource not found : '.$php_self);
            }
            /* save GLOBALS $_SESSION */
            file_put_contents(self::$config['SESSION_SAVE_PATH'].DS.$_COOKIE[self::$config['SESSION_NAME']],serialize($_SESSION));
        });

        /*
         * start http server
         * */
        self::$http->start();
    }
    
    public static function instance(){
        if(is_null(self::$instance)){
            self::$instance = new static();
        }
        return self::$instance;
    }

}